let {mat4, vec3} = require('gl-matrix');


let tmpv1 = vec3.create();
let tmpv2 = vec3.create();
let tmpMat1 = mat4.create();

class OrthoCamera {

    constructor(pos,
                target = vec3.fromValues(0, 0, 0),
                up = vec3.fromValues(0, 1, 0)) {

        // const
        this.near = 1;
        this.far = 100;

        this.projMatrix = mat4.create();
        this.viewMatrix = mat4.create();

        this.position = vec3.fromValues(pos[0], pos[1], pos[2]);
        this.target = vec3.fromValues(target[0], target[1], target[2]);
        this.up = vec3.fromValues(up[0], up[1], up[2]);
    }

    // 保持宽高比
    calProjMatrix(width, height) {
        let ratio = width / height;
        let scale = 20;
        mat4.ortho(this.projMatrix,
            -ratio * scale,
            ratio * scale,
            -1 * scale,
            1  * scale,
            this.near,
            this.far
        );
    }

    calViewMatrix() {
        mat4.lookAt(this.viewMatrix, this.position, this.target, this.up);
    }

    slide_left_to_right(degress) {

        // camera -z
        let dir = vec3.sub(tmpv1, this.target, this.position);
        let len = vec3.length(dir);

        let rad = degress * Math.PI / 180;
        mat4.fromYRotation(tmpMat1, rad);
        vec3.transformMat4(dir, dir, tmpMat1);
        vec3.normalize(dir, dir);
        vec3.scale(dir, dir, -len);
        vec3.add(this.position, this.target, dir);
    }

    slide_down_to_up(degress) {

        // camera -z
        let dir = vec3.sub(tmpv1, this.target, this.position);
        let left = vec3.cross(tmpv2, dir, this.up);
        vec3.normalize(left, left);

        let len = vec3.length(dir);
        let rad = degress * Math.PI / 180;

        mat4.fromRotation(tmpMat1, rad, left);
        vec3.transformMat4(dir, dir, tmpMat1);
        vec3.normalize(dir, dir);

        // 防止出现万向节锁
        if (Math.abs(dir[1]) > 0.8) {
            return;
        }

        vec3.scale(dir, dir, -len);
        vec3.add(this.position, this.target, dir);
    }

    // 移动
    translateX(value) {
        // camera -z
        let dir = vec3.sub(tmpv1, this.target, this.position);
        let left = vec3.cross(tmpv2, dir, this.up);
        vec3.normalize(left, left);
        vec3.scale(left, left, value);
        vec3.add(this.target, this.target, left);
        vec3.add(this.position, this.position, left);
    }

    translateZ(value, fly = false) {

        // camera -z
        let dir = vec3.sub(tmpv1, this.target, this.position);
        vec3.normalize(dir, dir);
        vec3.scale(dir, dir, value);

        if (!fly) {
            dir[1] = 0;
        }

        vec3.add(this.target, this.target, dir);
        vec3.add(this.position, this.position, dir);
    }

}

module.exports = OrthoCamera;
